import cloneDeep from 'lodash/cloneDeep';
import ATransfer from '../transfer';
import AInputSearch from '../input/Search';
import ATree from '../tree';
import PropTypes from '../_util/vue-types';

export default {
  name: 'CTransferTree',
  props: {
    disabled: PropTypes.bool.def(false),
    titles: PropTypes.array.def(['left', 'right']),
    leftData: PropTypes.array.isRequired,
    rightData: PropTypes.array.isRequired,
    fieldMap: PropTypes.object.def({
      key: 'id',
      title: 'name',
    }),

    listStyle: PropTypes.object.def({
      //配合flex一起使用
      width: '40%',
      height: 'auto',
      maxHeight: '600px',
    }),
  },
  data() {
    this.leftSourceMap = {};
    this.rightSourceMap = {};
    return {
      dataSource: [],

      leftSource: [],
      rightSource: [],

      sourceSelectedKeys: [],
      targetSelectedKeys: [],

      targetKeys: [],

      leftSearchContent: '',
      rightSearchContent: '',
    };
  },
  watch: {
    leftData: {
      handler(val) {
        let fn = (data, arr) => {
          data.forEach(item => {
            arr.push({
              [this.fieldMap.key]: item.key,
              [this.fieldMap.title]: item.title,
              key: item.key,
              title: item.title,
            });
            item.buttonList && fn(item.buttonList, arr);
            item.childrenList && fn(item.childrenList, arr);
          });
          return arr;
        };

        this.leftSourceMap = {};
        this.leftSource = this.formatterData(val, this.leftSourceMap);
        this.dataSource = fn(this.leftSource, []);
      },
      immediate: true,
    },
    rightData: {
      handler(val) {
        this.rightSourceMap = {};
        this.rightSource = this.formatterData(val, this.rightSourceMap);
        this.targetKeys = this.getTargetKeys(this.rightSource);
      },
      immediate: true,
    },
  },
  methods: {
    formatterData(val, sourceMap, lastIndex, isButton) {
      return val.map((item, index) => {
        let currentIndex = isButton ? 'b' + index : String(index);
        let aliasIndex = lastIndex ? `${lastIndex}-${currentIndex}` : currentIndex;

        Object.assign(item, {
          key: String(item[this.fieldMap.key]),
          title: item[this.fieldMap.title],
          aliasIndex,
          buttonList:
            item.buttonList && this.formatterData(item.buttonList, sourceMap, aliasIndex, true),
          childrenList:
            item.childrenList && this.formatterData(item.childrenList, sourceMap, aliasIndex),
        });

        sourceMap[aliasIndex] = item;
        return item;
      });
    },
    getTargetKeys(val) {
      let targetKeys = [];
      val.forEach(item => {
        targetKeys.push(item.key);
        item.buttonList && targetKeys.push(...this.getTargetKeys(item.buttonList));
        item.childrenList && targetKeys.push(...this.getTargetKeys(item.childrenList));
      });
      return targetKeys;
    },
    //eslint-disable-next-line
    handleBtnChange(nextTargetKeys, direction, moveKeys) {
      this.targetKeys = nextTargetKeys;

      let fn = (arr, tempArr) => {
        arr.forEach(item => {
          if (nextTargetKeys.includes(item.key)) {
            let buttonList = [];
            item.buttonList &&
              item.buttonList.forEach(itemBtn => {
                nextTargetKeys.includes(itemBtn.key) &&
                  buttonList.push({
                    ...itemBtn,
                    checked: false,
                    disabled: false,
                  });
              });
            //选中按钮的时候，菜单必定选中
            tempArr.push({
              ...item,
              checked: false,
              disabled: false,
              buttonList,
              childrenList: item.childrenList && fn(item.childrenList, []),
            });
          }
        });
        return tempArr;
      };

      this.rightSourceMap = {};
      let rightSource = fn(cloneDeep(this.leftSource), []);
      this.rightSource = this.formatterData(rightSource, this.rightSourceMap);
    },
    selectChange(sourceSelectedKeys, targetSelectedKeys) {
      this.sourceSelectedKeys = sourceSelectedKeys;
      this.targetSelectedKeys = targetSelectedKeys;
    },

    changeFn(item) {
      this.$emit('valueChanged', item);
    },
    //供外部调用
    getSelectedData() {
      let fn = source => {
        let arr = [];
        source.forEach(item => {
          arr.push({
            ...item,
            childrenList: null,
          });
          if (item.childrenList && item.childrenList.length) {
            arr = arr.concat(fn(item.childrenList));
          }
        });
        return arr;
      };

      return fn(this.rightSource);
    },
  },
  render(h) {
    let {
      titles,
      disabled,
      listStyle,

      dataSource,
      leftSource,
      rightSource,
      leftSourceMap,
      rightSourceMap,

      sourceSelectedKeys,
      targetSelectedKeys,
      targetKeys,

      selectChange,
      handleBtnChange,
    } = this;

    let _this = this;
    let selectedKeys = [...sourceSelectedKeys, ...targetSelectedKeys];

    let scopedSlots = {
      children: slotData => {
        let {
          props: { titleText, disabled },
          on: { itemSelect },
        } = slotData;
        let isLeft = titleText === titles[0];

        let sourceFilter = (arr, tempArr, filterContent) => {
          arr.forEach(item => {
            if (
              item.title.includes(filterContent) ||
              (item.buttonList &&
                item.buttonList.length &&
                item.buttonList.some(itemBtn => itemBtn.title.includes(filterContent)))
            ) {
              tempArr.push(item);
            } else {
              let childrenList =
                item.childrenList &&
                item.childrenList.length &&
                sourceFilter(item.childrenList, [], filterContent);
              childrenList.length &&
                tempArr.push({
                  ...item,
                  childrenList,
                });
            }
          });
          return tempArr;
        };

        let tempLeftSource = sourceFilter(leftSource, [], _this.leftSearchContent);
        let tempRightSource = sourceFilter(rightSource, [], _this.rightSearchContent);

        let leftFn = arr => {
          arr.forEach(item => {
            if (targetKeys.includes(item.key)) {
              item.checked = true;
              item.disabled = true;
            } else {
              item.checked = item.disabled ? false : sourceSelectedKeys.includes(item.key);
              item.disabled = false;
            }
            item.buttonList &&
              item.buttonList.forEach(itemBtn => {
                let isTargetIncludeKey = targetKeys.includes(itemBtn.key);
                itemBtn.checked =
                  itemBtn.disabled || isTargetIncludeKey
                    ? isTargetIncludeKey
                    : sourceSelectedKeys.includes(itemBtn.key);
                itemBtn.disabled = isTargetIncludeKey;
              });
            item.childrenList && leftFn(item.childrenList);
          });

          return arr;
        };

        let rightFn = arr => {
          arr.forEach(item => {
            item.checked = targetSelectedKeys.includes(item.key);

            item.buttonList &&
              item.buttonList.forEach(itemBtn => {
                itemBtn.checked = targetSelectedKeys.includes(itemBtn.key);
              });

            item.childrenList && rightFn(item.childrenList);
          });

          return arr;
        };

        let _leftSource = leftFn(tempLeftSource);

        let _rightSource = rightFn(tempRightSource);

        let searchInputChanged = value => {
          if (isLeft) {
            _this.leftSearchContent = value;
          } else {
            _this.rightSearchContent = value;
          }
        };

        let currentSourceMap = isLeft ? leftSourceMap : rightSourceMap;

        let valueChanged = ({ checked, aliasIndex }) => {
          if (isLeft) {
            if (checked) {
              Object.keys(currentSourceMap).forEach(mapKey => {
                //当前节点及其父级
                if (aliasIndex.startsWith(mapKey)) {
                  let curNode = currentSourceMap[mapKey];
                  if (aliasIndex === mapKey || !curNode.checked) {
                    setTimeout(() => {
                      itemSelect(curNode.key, checked);
                    });
                  }
                }
              });
            } else {
              Object.keys(currentSourceMap).forEach(mapKey => {
                //当前节点的子级
                if (mapKey.startsWith(aliasIndex)) {
                  setTimeout(() => {
                    itemSelect(currentSourceMap[mapKey].key, checked);
                  });
                }
              });
            }
          } else {
            if (checked) {
              Object.keys(currentSourceMap).forEach(mapKey => {
                //当前节点的子级
                if (mapKey.startsWith(aliasIndex)) {
                  setTimeout(() => {
                    itemSelect(currentSourceMap[mapKey].key, checked);
                  });
                }
              });
            } else {
              Object.keys(currentSourceMap).forEach(mapKey => {
                //当前节点的父级
                if (aliasIndex.startsWith(mapKey)) {
                  setTimeout(() => {
                    itemSelect(currentSourceMap[mapKey].key, checked);
                  });
                }
              });
            }
          }
        };

        let slotTree = Object.keys(_this.$scopedSlots).reduce((lastVal, key) => {
          lastVal[key] = (...args) => _this.$scopedSlots[key](valueChanged, ...args);
          return lastVal;
        }, {});

        return (
          <div class="list-content-wrapper">
            <AInputSearch
              {...{
                attrs: {
                  disabled,
                  placeholder: '请输入搜索内容',
                },
                domProps: {
                  value: isLeft ? _this.leftSearchContent : _this.rightSearchContent,
                },
                on: {
                  'change.value': searchInputChanged,
                },
              }}
            />

            <div class="transfer-tree-content-wrapper">
              <ATree
                {...{
                  props: {
                    disabled,
                    replaceFields: {
                      key: 'id',
                      title: 'name',
                      children: 'childrenList',
                    },
                    treeData: isLeft ? _leftSource : _rightSource,
                  },
                  scopedSlots: slotTree,
                }}
              />
            </div>
          </div>
        );
      },
    };

    return (
      <div class="customTransferTree">
        <ATransfer
          {...{
            props: {
              titles,
              disabled,
              listStyle,
              dataSource,
              selectedKeys,
              targetKeys,
            },
            on: {
              selectChange,
              change: handleBtnChange,
            },
            scopedSlots,
          }}
        />
      </div>
    );
  },
};
